package com.kxmall.web.controller.task.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.kxmall.common.core.domain.PageQuery;
import com.kxmall.common.core.page.TableDataInfo;
import com.kxmall.common.enums.RiderOrderStatusType;
import com.kxmall.common.exception.ServiceException;
import com.kxmall.common.utils.redis.RedisUtils;
import com.kxmall.order.biz.OrderRiderBizService;
import com.kxmall.rider.domain.KxRiderItem;
import com.kxmall.rider.domain.KxRiderOrder;
import com.kxmall.rider.domain.vo.KxRiderItemVo;
import com.kxmall.rider.domain.vo.KxRiderOrderVo;
import com.kxmall.rider.domain.vo.RiderOrderStatisticalDTO;
import com.kxmall.rider.domain.vo.RiderStatisticalDTO;
import com.kxmall.rider.mapper.KxRiderItemMapper;
import com.kxmall.rider.mapper.KxRiderOrderMapper;
import com.kxmall.web.controller.task.service.TaskCenterService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

/**
 * @description: 配送中心业务接口
 * @author: kxmall
 * @date: 2020/03/01 19:34
 **/
@Service
public class TaskCenterServiceImpl implements TaskCenterService {


    @Resource
    private KxRiderItemMapper riderSpuMapper;

    @Resource
    private KxRiderOrderMapper riderOrderMapper;

    @Resource
    OrderRiderBizService orderRiderBizService;


    private static final Logger logger = LoggerFactory.getLogger(TaskCenterServiceImpl.class);

    private static final Integer RIDER_ORDER_LOCK_WAITING_TIME = 30;
    private static final String RIDER_ORDER_STATUS_LOCK = "RIDER_ORDER_STATUS_LOCK";

    @Override
    public TableDataInfo<KxRiderOrderVo> list(Integer status, Integer page, Integer limit, Long riderId) throws ServiceException {
        if (ObjectUtils.isEmpty(status)) {
            throw new ServiceException("骑手订单状态不存在");
        }
        QueryWrapper<KxRiderOrder> wrapper = new QueryWrapper<>();
        wrapper.eq("status", status);
        wrapper.eq("rider_id", riderId);
        if (RiderOrderStatusType.ABNORMAL.getCode().equals(status) || RiderOrderStatusType.COMPLETED.getCode().equals(status)) {
            wrapper.orderByDesc("update_time");
        } else {
            // 越先分配的越排在前面
            wrapper.orderByDesc("predict_time");
        }
        PageQuery pageQuery = new PageQuery();
        pageQuery.setPageNum(page - 1);
        pageQuery.setPageSize(limit);

        Page<KxRiderOrderVo> riderOrderDOList = riderOrderMapper.selectVoPage(pageQuery.build(), wrapper);
        return TableDataInfo.build(riderOrderDOList);
    }

    @Override
    public KxRiderOrderVo detail(Long riderOrderId, Long riderId) throws ServiceException {
        KxRiderOrder riderOrderDO = riderOrderMapper.selectById(riderOrderId);
        if (riderOrderDO == null) {
            throw new ServiceException("骑手订单不存在！");
        }
        QueryWrapper<KxRiderItem> wrapper = new QueryWrapper<>();
        wrapper.eq("rider_order_id", riderOrderId);
        List<KxRiderItemVo> riderSpuDOS = riderSpuMapper.selectVoList(wrapper);
        if (riderSpuDOS == null || riderSpuDOS.size() == 0) {
            throw new ServiceException("骑手订单商品不存在！");
        }
        KxRiderOrderVo riderOrderDTO = new KxRiderOrderVo();
        BeanUtils.copyProperties(riderOrderDO, riderOrderDTO);
        riderOrderDTO.setRiderItemVoList(riderSpuDOS);
        return riderOrderDTO;
    }


    @Override
    public String begin(Long riderOrderId, BigDecimal lng, BigDecimal lat, Long riderId) throws ServiceException {
        KxRiderOrder riderOrderDO = riderOrderMapper.selectById(riderOrderId);
        if (riderOrderDO == null) {
            throw new ServiceException("配送员订单不存在");
        }
        if (!((RiderOrderStatusType.WAITING.getCode()).equals(riderOrderDO.getStatus()) || (RiderOrderStatusType.ABNORMAL.getCode()).equals(riderOrderDO.getStatus()))) {
            throw new ServiceException("当前配送员订单状态不能执行该操作");
        }
        String orderNo = riderOrderDO.getOrderNo();
        Lock lock = RedisUtils.lock(RIDER_ORDER_STATUS_LOCK + orderNo);
        try {
            if (lock.tryLock(RIDER_ORDER_LOCK_WAITING_TIME, TimeUnit.SECONDS)) {
                riderOrderDO.setStatus(RiderOrderStatusType.DISPENSE.getCode());
                riderOrderDO.setUpdateTime(new Date());
                if (riderOrderMapper.updateById(riderOrderDO) > 0) {
                    orderRiderBizService.sendRiderMessageBusiness(riderOrderDO.getOrderNo(), RiderOrderStatusType.DISPENSE, riderOrderDO.getRiderId(), null);
                    return "ok";
                }
                throw new ServiceException("配送员订单状态更新异常，请稍后再试");
            } else {
                throw new ServiceException("配送订单系统繁忙~");
            }
        } catch (Exception e) {
            logger.error("[订单配送状态变更] 异常", e);
            throw new ServiceException("配送订单系统未知异常");
        } finally {
            lock.unlock();
        }
    }

    @Override
    public String abnormal(Long riderOrderId, String reason, BigDecimal lng, BigDecimal lat, Long riderId) throws ServiceException {
        KxRiderOrder riderOrderDO = riderOrderMapper.selectById(riderOrderId);
        if (riderOrderDO == null) {
            throw new ServiceException("配送员订单不存在");
        }
        if (!((RiderOrderStatusType.DISPENSE.getCode()).equals(riderOrderDO.getStatus()))) {
            throw new ServiceException("当前配送员订单状态不能执行该操作");
        }
        String orderNo = riderOrderDO.getOrderNo();
        Lock lock = RedisUtils.lock(RIDER_ORDER_STATUS_LOCK + orderNo);
        try {
            if (lock.tryLock(RIDER_ORDER_LOCK_WAITING_TIME, TimeUnit.SECONDS)) {
                riderOrderDO.setStatus(RiderOrderStatusType.ABNORMAL.getCode());
                riderOrderDO.setAbnormal(RiderOrderStatusType.ABNORMAL.getCode());
                riderOrderDO.setUpdateTime(new Date());
                riderOrderDO.setReason(reason);
                if (riderOrderMapper.updateById(riderOrderDO) > 0) {
                    orderRiderBizService.sendRiderMessageBusiness(riderOrderDO.getOrderNo(), RiderOrderStatusType.ABNORMAL, riderOrderDO.getRiderId(), reason);
                    return "ok";
                }
                throw new ServiceException("配送员订单状态更新异常，请稍后再试");
            } else {
                throw new ServiceException("配送订单系统繁忙~");
            }
        } catch (Exception e) {
            logger.error("[订单配送状态变更] 异常", e);
            throw new ServiceException("配送订单系统未知异常");
        } finally {
            lock.unlock();
        }
    }

    @Override
    public String complete(Long riderOrderId, BigDecimal lng, BigDecimal lat, Long riderId) throws ServiceException {
        KxRiderOrder riderOrderDO = riderOrderMapper.selectById(riderOrderId);
        if (riderOrderDO == null) {
            throw new ServiceException("配送员订单不存在");
        }
        if (!((RiderOrderStatusType.DISPENSE.getCode()).equals(riderOrderDO.getStatus())
                || (RiderOrderStatusType.TIMEOUT.getCode()).equals(riderOrderDO.getStatus())
                || (RiderOrderStatusType.ABNORMAL.getCode()).equals(riderOrderDO.getStatus()))) {
            throw new ServiceException("当前配送员订单状态不能执行该操作");
        }
        String orderNo = riderOrderDO.getOrderNo();
        Lock lock = RedisUtils.lock(RIDER_ORDER_STATUS_LOCK + orderNo);
        try {
            if (lock.tryLock(RIDER_ORDER_LOCK_WAITING_TIME, TimeUnit.SECONDS)) {
                riderOrderDO.setStatus(RiderOrderStatusType.COMPLETED.getCode());
                riderOrderDO.setUpdateTime(new Date());
                if (riderOrderMapper.updateById(riderOrderDO) > 0) {
                    orderRiderBizService.sendRiderMessageBusiness(riderOrderDO.getOrderNo(), RiderOrderStatusType.COMPLETED, riderOrderDO.getRiderId(), null);
                    return "ok";
                }
                throw new ServiceException("配送员订单状态更新异常，请稍后再试");
            } else {
                throw new ServiceException("配送订单系统繁忙~");
            }
        } catch (Exception e) {
            logger.error("[订单配送状态变更] 异常", e);
            throw new ServiceException("配送订单系统未知异常");
        } finally {
            lock.unlock();
        }
    }


    @Override
    public RiderOrderStatisticalDTO statistical(Long riderId) throws ServiceException {
        if (riderId != null) {
            List<RiderStatisticalDTO> riderStatisticalDTOList = riderOrderMapper.statisticalCount(riderId);
            if (riderStatisticalDTOList != null && riderStatisticalDTOList.size() > 0) {
                RiderOrderStatisticalDTO riderOrderStatisticalDTO = new RiderOrderStatisticalDTO();
                for (RiderStatisticalDTO riderStatisticalDTO : riderStatisticalDTOList) {
                    if (RiderOrderStatusType.WAITING.getCode().equals(riderStatisticalDTO.getStatus())) {
                        riderOrderStatisticalDTO.setWaitingCount(riderStatisticalDTO.getCount());
                    } else if (RiderOrderStatusType.TIMEOUT.getCode().equals(riderStatisticalDTO.getStatus())) {
                        riderOrderStatisticalDTO.setTimeoutCount(riderStatisticalDTO.getCount());
                    } else if (RiderOrderStatusType.ABNORMAL.getCode().equals(riderStatisticalDTO.getStatus())) {
                        riderOrderStatisticalDTO.setAbnormalCount(riderStatisticalDTO.getCount());
                    } else if (RiderOrderStatusType.COMPLETED.getCode().equals(riderStatisticalDTO.getStatus())) {
                        riderOrderStatisticalDTO.setCompletedCount(riderStatisticalDTO.getCount());
                    } else if (RiderOrderStatusType.DISPENSE.getCode().equals(riderStatisticalDTO.getStatus())) {
                        riderOrderStatisticalDTO.setDispenseCount(riderStatisticalDTO.getCount());
                    }
                }
                return riderOrderStatisticalDTO;
            }
        }
        return null;
    }

    @Override
    public TableDataInfo<KxRiderOrderVo> income(Integer page, Integer limit, Long riderId) throws ServiceException {
        QueryWrapper<KxRiderOrder> wrapper = new QueryWrapper<>();
        wrapper.eq("rider_id", riderId);
        wrapper.eq("status", 4);

        PageQuery pageQuery = new PageQuery();
        pageQuery.setPageNum(page - 1);
        pageQuery.setPageSize(limit);

        Page<KxRiderOrderVo> riderOrderDOList = riderOrderMapper.selectVoPage(pageQuery.build(), wrapper);
        return TableDataInfo.build(riderOrderDOList);
    }

    @Override
    public BigDecimal countIncome(Long riderId) throws ServiceException {
        return riderOrderMapper.selectSumIncome(riderId);
    }
}
